﻿using Microsoft.Extensions.Caching.Distributed;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

namespace Fast.Extensions.Caching
{
    /// <summary>
    /// <typeparamref name="TCacheItem" /> 类型的分布式缓存。
    /// </summary>
    /// <typeparam name="TCacheItem"></typeparam>
    public interface IDistributedCache<TCacheItem> : IDistributedCache<TCacheItem, string>
        where TCacheItem : class
    {

    }
    /// <summary>
    /// <typeparamref name="TCacheItem" /> 类型的分布式缓存，
    /// 使用 <typeparamref name="TCacheKey"/> 类型做为缓存键
    /// </summary>
    /// <typeparam name="TCacheItem">要缓存的类型</typeparam>
    /// <typeparam name="TCacheKey">要从缓存中检索的缓存项的键类型</typeparam>
    public interface IDistributedCache<TCacheItem, TCacheKey>
        where TCacheItem : class
    {
        /// <summary>
        /// 获取指定缓存键的缓存项。如果找不到指定缓存键的缓存项，则返回null
        /// </summary>
        /// <param name="key">要从缓存中检索的缓存项的键</param>
        /// <returns>缓存项或null</returns>
        TCacheItem Get(
            TCacheKey key
        );

        /// <summary>
        /// 获取指定缓存键的缓存项。如果找不到指定缓存键的缓存项，则返回null
        /// </summary>
        /// <param name="key">要从缓存中检索的缓存项的键</param>
        /// <param name="token">任务的 <see cref="T:System.Threading.CancellationToken" /></param>
        /// <returns>缓存项或null</returns>
        Task<TCacheItem> GetAsync(
            TCacheKey key,
            CancellationToken token = default
        );

        /// <summary>
        /// 获取指定缓存键的多个缓存项
        /// </summary>
        /// <param name="keys">要从缓存中检索的缓存项的键</param>
        /// <returns>缓存项列表</returns>
        KeyValuePair<TCacheKey, TCacheItem>[] GetMany(
            IEnumerable<TCacheKey> keys
        );

        /// <summary>
        /// 获取指定缓存键的多个缓存项
        /// </summary>
        /// <param name="keys">要从缓存中检索的缓存项的键</param>
        /// <param name="token">任务的 <see cref="T:System.Threading.CancellationToken" /></param>
        /// <returns></returns>
        Task<KeyValuePair<TCacheKey, TCacheItem>[]> GetManyAsync(
           IEnumerable<TCacheKey> keys,
           CancellationToken token = default
        );

        /// <summary>
        /// 获取或添加指定缓存键的缓存项，
        /// 如果未找到指定缓存键的缓存项，则添加由 <paramref name="factory"/> 委托提供的缓存项，并返回提供的缓存项
        /// </summary>
        /// <param name="key">要从缓存中检索的缓存项的键</param>
        /// <param name="factory">当找不到<paramref name="key" />的缓存项时，factory委托用于提供缓存项 </param>
        /// <param name="optionsFactory">factory委托的缓存选项</param>
        /// <returns></returns>
        TCacheItem GetOrAdd(
            TCacheKey key,
            Func<TCacheItem> factory,
            Func<DistributedCacheEntryOptions> optionsFactory = null
        );

        /// <summary>
        /// 获取或添加指定缓存键的缓存项，
        /// 如果未找到指定缓存键的缓存项，则添加由 <paramref name="factory"/> 委托提供的缓存项，并返回提供的缓存项
        /// </summary>
        /// <param name="key">要从缓存中检索的缓存项的键</param>
        /// <param name="factory">当找不到<paramref name="key" />的缓存项时，factory委托用于提供缓存项 </param>
        /// <param name="optionsFactory">factory委托的缓存选项</param>
        /// <param name="token">任务的 <see cref="T:System.Threading.CancellationToken" /></param>
        /// <returns></returns>
        Task<TCacheItem> GetOrAddAsync(
            TCacheKey key,
            Func<Task<TCacheItem>> factory,
            Func<DistributedCacheEntryOptions> optionsFactory = null,
            CancellationToken token = default
        );

        /// <summary>
        /// 获取或添加指定缓存键的多个缓存项，
        /// 如果未找到指定缓存键的任何缓存项，则添加由 <paramref name="factory"/> 委托提供的缓存项，并返回提供的缓存项
        /// </summary>
        /// <param name="keys">要从缓存中检索的缓存项的键</param>
        /// <param name="factory">当找不到<paramref name="key" />的缓存项时，factory委托用于提供缓存项</param>
        /// <param name="optionsFactory">factory委托的缓存选项</param>
        /// <returns></returns>
        KeyValuePair<TCacheKey, TCacheItem>[] GetOrAddMany(
           IEnumerable<TCacheKey> keys,
           Func<IEnumerable<TCacheKey>, List<KeyValuePair<TCacheKey, TCacheItem>>> factory,
           Func<DistributedCacheEntryOptions> optionsFactory = null
        );

        /// <summary>
        /// 获取或添加指定缓存键的多个缓存项，
        /// 如果未找到指定缓存键的任何缓存项，则添加由 <paramref name="factory"/> 委托提供的缓存项，并返回提供的缓存项
        /// </summary>
        /// <param name="keys">要从缓存中检索的缓存项的键</param>
        /// <param name="factory">当找不到<paramref name="key" />的缓存项时，factory委托用于提供缓存项</param>
        /// <param name="optionsFactory">factory委托的缓存选项</param>
        /// <param name="token">任务的 <see cref="T:System.Threading.CancellationToken" /></param>
        /// <returns></returns>
        Task<KeyValuePair<TCacheKey, TCacheItem>[]> GetOrAddManyAsync(
            IEnumerable<TCacheKey> keys,
            Func<IEnumerable<TCacheKey>, Task<List<KeyValuePair<TCacheKey, TCacheItem>>>> factory,
            Func<DistributedCacheEntryOptions> optionsFactory = null,
            CancellationToken token = default
        );

        /// <summary>
        /// 为指定的缓存键设置缓存项值
        /// </summary>
        /// <param name="key">要从缓存中检索的缓存项的键</param>
        /// <param name="value">要在缓存中设置的缓存项值</param>
        /// <param name="options">值的缓存选项</param>
        void Set(
            TCacheKey key,
            TCacheItem value,
            DistributedCacheEntryOptions options = null
        );

        /// <summary>
        /// 为指定的缓存键设置缓存项值
        /// </summary>
        /// <param name="key">要从缓存中检索的缓存项的键</param>
        /// <param name="value">要在缓存中设置的缓存项值</param>
        /// <param name="options">值的缓存选项</param>
        /// <param name="token">任务的 <see cref="T:System.Threading.CancellationToken" /></param>
        /// <returns></returns>
        Task SetAsync(
            TCacheKey key,
            TCacheItem value,
            DistributedCacheEntryOptions options = null,
            CancellationToken token = default
        );

        /// <summary>
        /// 设置多个缓存项
        /// </summary>
        /// <param name="items">要在缓存上设置的项</param>
        /// <param name="options">值的缓存选项</param>
        void SetMany(
            IEnumerable<KeyValuePair<TCacheKey, TCacheItem>> items,
            DistributedCacheEntryOptions options = null
        );

        /// <summary>
        /// 设置多个缓存项
        /// </summary>
        /// <param name="items">要在缓存上设置的项</param>
        /// <param name="options">值的缓存选项</param>
        /// <param name="token">任务的 <see cref="T:System.Threading.CancellationToken" /></param>
        /// <returns></returns>
        Task SetManyAsync(
            IEnumerable<KeyValuePair<TCacheKey, TCacheItem>> items,
            DistributedCacheEntryOptions options = null,
            CancellationToken token = default
        );


        /// <summary>
        /// 刷新指定缓存键的缓存值，并重置其滑动过期超时
        /// </summary>
        /// <param name="key">要从缓存中检索的缓存项的键</param>
        void Refresh(
            TCacheKey key
        );

        /// <summary>
        /// 刷新指定缓存键的缓存值，并重置其滑动过期超时
        /// </summary>
        /// <param name="key">要从缓存中检索的缓存项的键</param>
        /// <param name="token">任务的 <see cref="T:System.Threading.CancellationToken" /></param>
        /// <returns></returns>
        Task RefreshAsync(
            TCacheKey key,
            CancellationToken token = default
        );

        /// <summary>
        /// 刷新指定缓存键的缓存值，并重置其滑动过期超时
        /// </summary>
        /// <param name="keys">要从缓存中检索的缓存项的键</param>
        void RefreshMany(
            IEnumerable<TCacheKey> keys
        );

        /// <summary>
        /// 刷新指定缓存键的缓存值，并重置其滑动过期超时
        /// </summary>
        /// <param name="keys">要从缓存中检索的缓存项的键</param>
        /// <param name="token">任务的 <see cref="T:System.Threading.CancellationToken" /></param>
        /// <returns></returns>
        Task RefreshManyAsync(
            IEnumerable<TCacheKey> keys,
            CancellationToken token = default
        );

        /// <summary>
        /// 从缓存中删除指定缓存键的缓存项。
        /// </summary>
        /// <param name="key">要从缓存中检索的缓存项的键</param>
        void Remove(
            TCacheKey key
        );

        /// <summary>
        /// 从缓存中删除指定缓存键的缓存项
        /// </summary>
        /// <param name="key">要从缓存中检索的缓存项的键</param>
        /// <param name="token">任务的 <see cref="T:System.Threading.CancellationToken" /></param>
        /// <returns></returns>
        Task RemoveAsync(
            TCacheKey key,
            CancellationToken token = default
        );

        /// <summary>
        /// 从缓存中删除指定缓存键的缓存项
        /// </summary>
        /// <param name="keys">要从缓存中检索的缓存项的键</param>
        void RemoveMany(
            IEnumerable<TCacheKey> keys
        );

        /// <summary>
        /// 从缓存中删除指定缓存键的缓存项
        /// </summary>
        /// <param name="keys">要从缓存中检索的缓存项的键</param>
        /// <param name="token">任务的 <see cref="T:System.Threading.CancellationToken" /></param>
        /// <returns></returns>
        Task RemoveManyAsync(
            IEnumerable<TCacheKey> keys,
            CancellationToken token = default
        );
    }
}
